package com.example.library.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.library.common.ResultCode;
import com.example.library.dto.BaseQueryRequest;
import com.example.library.entity.Book;
import com.example.library.mapper.BookMapper;
import com.example.library.service.BookService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 图书服务实现类
 *
   */
@Slf4j
@Service
@RequiredArgsConstructor
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService {

    private final BookMapper bookMapper;

    @Override
    public IPage<Book> getBookPage(BaseQueryRequest queryRequest) {
        Page<Book> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        return bookMapper.selectBookPage(page,
                queryRequest.getKeyword(),
                null,
                null,
                null,
                null);
    }

    @Override
    public IPage<Book> getBooksByCategory(Long categoryId, BaseQueryRequest queryRequest) {
        Page<Book> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        // 使用简单的查询方法，因为Mapper中没有分页版本
        List<Book> books = bookMapper.selectBooksByCategory(categoryId, null);
        page.setRecords(books);
        page.setTotal(books.size());
        return page;
    }

    @Override
    public IPage<Book> searchBooks(String keyword, BaseQueryRequest queryRequest) {
        Page<Book> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        return bookMapper.searchBooks(page, keyword);
    }

    @Override
    public List<Book> getPopularBooks(Integer limit) {
        return bookMapper.selectPopularBooks(limit);
    }

    @Override
    public List<Book> getLatestBooks(Integer limit) {
        return bookMapper.selectLatestBooks(limit);
    }

    @Override
    public List<Book> getRecommendedBooks(Integer limit) {
        return bookMapper.selectRecommendedBooks(limit);
    }

    @Override
    public Book findByIsbn(String isbn) {
        return bookMapper.findByIsbn(isbn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createBook(Book book) {
        // 检查ISBN是否存在
        if (StringUtils.isNotBlank(book.getIsbn()) && existsByIsbn(book.getIsbn())) {
            throw new RuntimeException("ISBN号已存在");
        }

        // 设置默认值
        if (book.getStatus() == null) {
            book.setStatus(Book.STATUS_ONLINE);
        }
        if (book.getTotalQuantity() == null) {
            book.setTotalQuantity(0);
        }
        if (book.getAvailableQuantity() == null) {
            book.setAvailableQuantity(book.getTotalQuantity());
        }

        // 验证库存数量
        if (book.getAvailableQuantity() > book.getTotalQuantity()) {
            throw new RuntimeException("可借数量不能大于总数量");
        }

        LocalDateTime now = LocalDateTime.now();
        book.setCreatedTime(now);
        book.setUpdatedTime(now);
        return save(book);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBook(Book book) {
        Book existingBook = getById(book.getId());
        if (existingBook == null) {
            throw new RuntimeException(ResultCode.BOOK_NOT_FOUND.getMessage());
        }

        // 检查ISBN是否被其他图书使用
        if (StringUtils.isNotBlank(book.getIsbn()) &&
                !book.getIsbn().equals(existingBook.getIsbn()) &&
                existsByIsbn(book.getIsbn())) {
            throw new RuntimeException("ISBN号已被其他图书使用");
        }

        // 验证库存数量
        if (book.getAvailableQuantity() != null && book.getTotalQuantity() != null &&
                book.getAvailableQuantity() > book.getTotalQuantity()) {
            throw new RuntimeException("可借数量不能大于总数量");
        }

        book.setUpdatedTime(LocalDateTime.now());
        return updateById(book);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBook(Long bookId) {
        Book book = getById(bookId);
        if (book == null) {
            throw new RuntimeException(ResultCode.BOOK_NOT_FOUND.getMessage());
        }

        // 检查是否有未归还的借阅记录
        // 这里需要调用借阅记录服务检查，暂时跳过
        
        return removeById(bookId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteBooks(List<Long> bookIds) {
        // 检查是否有未归还的借阅记录
        // 这里需要调用借阅记录服务检查，暂时跳过
        
        return removeByIds(bookIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBookStatus(Long bookId, Integer status) {
        Book book = getById(bookId);
        if (book == null) {
            throw new RuntimeException(ResultCode.BOOK_NOT_FOUND.getMessage());
        }

        book.setStatus(status);
        return updateById(book);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateBookStatus(List<Long> bookIds, Integer status) {
        return bookMapper.batchUpdateStatus(bookIds, status) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBookStock(Long bookId, Integer totalCount, Integer availableCount) {
        Book book = getById(bookId);
        if (book == null) {
            throw new RuntimeException(ResultCode.BOOK_NOT_FOUND.getMessage());
        }

        // 验证库存数量
        if (availableCount > totalCount) {
            throw new RuntimeException("可借数量不能大于总数量");
        }

        book.setTotalQuantity(totalCount);
        book.setAvailableQuantity(availableCount);
        return updateById(book);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean borrowBook(Long bookId) {
        Book book = getById(bookId);
        if (book == null) {
            throw new RuntimeException(ResultCode.BOOK_NOT_FOUND.getMessage());
        }

        if (!isBookAvailable(bookId)) {
            throw new RuntimeException(ResultCode.BOOK_NOT_AVAILABLE.getMessage());
        }

        return bookMapper.updateAvailableQuantity(bookId, -1) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean returnBook(Long bookId) {
        Book book = getById(bookId);
        if (book == null) {
            throw new RuntimeException(ResultCode.BOOK_NOT_FOUND.getMessage());
        }

        return bookMapper.updateAvailableQuantity(bookId, 1) > 0;
    }

    @Override
    public boolean isBookAvailable(Long bookId) {
        Book book = getById(bookId);
        return book != null && book.isAvailable();
    }

    @Override
    public boolean existsByIsbn(String isbn) {
        return findByIsbn(isbn) != null;
    }

    @Override
    public List<Book> getLowStockBooks(Integer threshold) {
        return bookMapper.selectLowStockBooks(threshold);
    }

    @Override
    public Object getBookStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 总图书数
        statistics.put("totalBooks", count());
        
        // 上架图书数
        statistics.put("onShelfBooks", bookMapper.countBooks(null, Book.STATUS_ON_SHELF));
        
        // 下架图书数
        statistics.put("offShelfBooks", bookMapper.countBooks(null, Book.STATUS_OFF_SHELF));
        
        // 总库存
        statistics.put("totalStock", bookMapper.sumTotalCount());
        
        // 可借库存
        statistics.put("availableStock", bookMapper.sumAvailableCount());
        
        // 已借出数量
        Long totalStock = (Long) statistics.get("totalStock");
        Long availableStock = (Long) statistics.get("availableStock");
        statistics.put("borrowedCount", totalStock - availableStock);
        
        // 库存不足图书数（可借数量小于5）
        statistics.put("lowStockBooks", bookMapper.countLowStockBooks(5));
        
        return statistics;
    }

}